# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.

from os import path
import random

integer_types = ['Int8', 'Int16', 'Int32', 'Int64', 'IntNative', 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'UIntNative']
number_types = integer_types + ['Float16', 'Float32', 'Float64']
other_types = ['String', 'Rune', 'Bool', 'Unit', 'Tuple', 'Array', 'Range', 'C', 'S']
types = number_types + other_types
default_value_map = {'Bool': 'true', 'Unit': '()', 'Array': '[1]', 'Rune': "'1'", 'Range': '1..2',
                     'String': '"1"', 'Tuple': '(1, 1)', 'C': 'C(1)', 'S': 'S(1)'}

def default_value(ty : str) -> str:
  if ty in integer_types: return '1'
  if 'Float' in ty: return '1.0'
  return default_value_map[ty]

custom_type_template = '''
%s {
    let x : Int64

    init(y : Int64) { x = y }

    operator func ==(other : %s) { x == other.x }
}
'''
decl_map = {'Array': '\ntype Array = Array<Int64>\n', 'Tuple': '\ntype Tuple = (Int64, Int64)\n',
            'Range': '\ntype Range = Range<Int64>\n', 'Function': '\ntype Function = (Int64) -> Int64\n',
            'C': custom_type_template % ('class C', 'C'), 'S': custom_type_template % ('struct S', 'S')}
def decl(ty : str) -> str:
  if ty in decl_map: return decl_map[ty]
  return ''

dir = path.dirname(path.realpath(__file__))
path = dir + '/test_' + path.basename(dir) + '_{}.cj'
template = '''
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

/*
  @Assertion:   4.7.3(6) Therefore, the type of expr must be the same as the return type of the function.
  @Description: %s
  @Mode: %s
  @Negative: %s
  @Structure: single
  @CompileWarning: ignore
  @Comment: Auto-generated by gen.py
*/
%s
'''
negative_template = template % ('Checks that value of type {t1} cannot be returned from a function with return type {t2}.',
                                'compileonly', 'yes', '''{}
func f() : {t2} {{
    let r : {t1} = {}
    return r
}}

main() {{ }}''')
positive_test =  template.format() % ('Checks that value of type T can be returned from a function with return type T for various T,',
'run', 'no', '\nfunc f<T>(x : T) { return x }\n' + ''.join([decl(t) for t in types]) +
 ''.join(['\nfunc f{t}(x : {t}) {{ return x }}\n'.format(t=t) for t in types]) + '''
main() {
    %s

    %s

    0
}''' % ('\n    '.join(['f%s(%s)' % (t, default_value(t)) for t in types]),
        '\n    '.join(['f<%s>(%s)' % (t, default_value(t)) for t in types])))
counter = 1

def write_counted(contents : str):
  global counter
  with open(path.format(str(counter).zfill(3)), 'w') as file:
    file.write(contents)
    counter += 1

write_counted(positive_test)
random.seed(123)
limit = 100
tests = [negative_template.format(decl(t1) + decl(t2), default_value(t1), t1=t1, t2=t2) for t1 in types for t2 in types if t1 != t2]
for test in random.sample(tests, limit):
  write_counted(test)
